//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <cevent.h>
#include <cmutex.h>
#include <cprocess.h>
#include <pcentral.h>
#include <pseudo.h>
#include <dhostmgr.h>
#include <stdio.h>
#include <aura.h>

#define HOST_NAME_LENGTH 256

CHostingManager::CHostingManager()
{
    m_hostLock.Initialize();
}

PInterface CHostingManager::Probe(
    /* [in] */ REIID riid)
{
    if (riid == EIID_IInterface) {
        return (PInterface)(IHostingManager *)this;
    }
    else if (riid == EIID_IHostingManager) {
        return (IHostingManager *)this;
    }
    else if (riid == EIID_CLASS_INFO) {
        return (PInterface)&ECLSID_CHostingManager;
    }
    else if (riid == EIID_INTERFACE_INFO) {
        return (PInterface)&EIID_IHostingManager;
    }

    return NULL;
}

UInt32 CHostingManager::AddRef(void)
{
    return 3;
}

UInt32 CHostingManager::Release(void)
{
    return 2;
}

ECode CHostingManager::Aggregate(
    /* [in] */ AggregateType type,
    /* [in] */ PInterface pObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CHostingManager::GetDomain(
    /* [out] */ PInterface *ppObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CHostingManager::GetOne(
    /* [out] */ IAppletHosting ** ppHost)
{
    WaitResult wr;
    ECode ec = NOERROR;
//    CProcess *pProc;
    ProcessId procid;
    Boolean bExist = FALSE;
    wchar_t dhostName[HOST_NAME_LENGTH];

//    pProc = new CProcess(0);
//    if (NULL == pProc) return E_OUT_OF_MEMORY;
//    pProc->AddRef();

    m_hostLock.Lock(&wr);
//    m_hostEvent.Clear();

    ec = CPseudoCentral::CreateNamedEvent(L"DomainHostEvent", FALSE, 
                                0, &bExist, &m_hostEventId);
    if (FAILED(ec)) goto ErrorExit;

//    ec = pProc->Start(L"SuperExe.exe", L"-Hosting");
    ec = CPseudoCentral::Process_Create(ThreadPriorityRank_Normal, 0, 
                                L"SuperExe.exe", L"-Hosting", &procid);
    if (FAILED(ec)) goto ErrorExit;

//    m_hostEvent.TryWait(c_nWaitHostTimeout, &wr, (EventState *)ppHost);
    ec = CPseudoCentral::TrywaitNamedEvent(m_hostEventId, c_nWaitHostTimeout, 
                                &wr, (EventState *)ppHost);
    if (FAILED(ec)) goto ErrorExit;
    if ((WaitResult_OK == wr) && (NULL != *ppHost)) {
        Aura_swprintf((Aura_PWChar)dhostName, 
                        (const Aura_WChar *)L"DominaHost%d", procid);
        ec = CPseudoSyscall::FindRunningObject(dhostName, (PInterface*)ppHost);
        if (FAILED(ec)) goto ErrorExit;
        (*ppHost)->AddRef();
    }
    else {
        ec = E_TIMED_OUT;
    }

ErrorExit:
    m_hostLock.Unlock();
//    pProc->Release();
    return ec;
}

ECode CHostingManager::Register(
    /* [in] */ IAppletHosting * pHost)
{
    if (NULL == pHost) {
        return E_INVALID_ARGUMENT;
    }

    Boolean bExist = FALSE;
    ProcessId procid;
    wchar_t dhostName[HOST_NAME_LENGTH];
    ECode ec = NOERROR;

    pHost->AddRef();

//    m_hostEvent.Notify((EventState)pHost);
    ec = CPseudoCentral::CreateNamedEvent(L"DomainHostEvent", FALSE, 
                        0, &bExist, &m_hostEventId);
    if (FAILED(ec))
        return ec;
    else if (!bExist) 
        return E_DOES_NOT_EXIST;

    ec = CPseudoKernel::Process_GetCurrentId(&procid);
    if (FAILED(ec)) return ec;

    Aura_swprintf((Aura_PWChar)dhostName, 
                        (const Aura_WChar *)L"DominaHost%d", procid);
    ec = CPseudoSyscall::RegisterRunningObject(dhostName, pHost);
    if (FAILED(ec)) return ec;

    CPseudoCentral::NotifyNamedEvent(m_hostEventId, 1);
    return ec;
}

ECode CHostingManager::Unregister(
    /* [in] */ IAppletHosting * pHost)
{
    if (NULL != pHost) {
        pHost->Release();
    }
    return NOERROR;
}
